home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / xsokoban / xdisp.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  14KB  |  621 lines

  1. #include <X11/Xlib.h>
  2. #include <X11/Xutil.h>
  3. #include <X11/keysym.h>
  4. #include <stdio.h>
  5. #include "sokoban.h"
  6. #include "help.h"
  7.  
  8. #define PRG_NAME "xsokoban"
  9.  
  10. #define BIT_H 30 
  11. #define BIT_W 30
  12.  
  13. #define FONT "9x15"
  14. #define DEF_CURSOR 102
  15.  
  16. #define HELPLINE ((BIT_H * MAXROW) + 30)
  17. #define STATUSLINE ((BIT_H * MAXROW) + 5)
  18.  
  19. #define HELP_H (BIT_H*MAXROW)
  20. #define HELP_W (BIT_W*MAXCOL)
  21.  
  22. extern short rows, cols, level, moves, pushes, packets, savepack;
  23. extern char  map[MAXROW+1][MAXCOL+1];
  24. extern char bitfilepath[1024];
  25. extern int optbitmap, optwalls;
  26.  
  27. char *wallname[] =
  28.    { "lonewall.xbm",
  29.      "southwall.xbm",
  30.      "westwall.xbm",
  31.      "llcrnrwall.xbm",
  32.      "northwall.xbm",
  33.      "vertiwall.xbm",
  34.      "ulcrnrwall.xbm",
  35.      "west_twall.xbm",
  36.      "eastwall.xbm",
  37.      "lrcrnrwall.xbm",
  38.      "horizwall.xbm",
  39.      "s_twall.xbm",
  40.      "urcrnrwall.xbm",
  41.      "east_twall.xbm",
  42.      "n_twall.xbm",
  43.      "centerwall.xbm" };
  44.  
  45. Pixmap goal, man, object, treasure, swalls[16], blank, work, help[2];
  46. Pixmap floor, saveman;
  47. Display *display;
  48. Window win;
  49. int screen;
  50. GC gc, rev, depth_rev;
  51. XFontStruct *font_info;
  52. unsigned int width, height, depth;
  53. char buf[100];
  54. int display_alloc = 0, font_alloc = 0, gc_alloc = 0, pix_alloc = 0;
  55. Colormap cmap;
  56. Cursor this_curs;
  57. XColor foreg, backg, curs, bordr;
  58.  
  59. int hlpscrn = -1;
  60.  
  61. void get_int(res, val, def_val)
  62. char *res;
  63. int *val, def_val;
  64. {
  65.   char *string;
  66.  
  67.   string = XGetDefault(display, PRG_NAME, res);
  68.   if(string)
  69.     *val = atoi(string);
  70.   else
  71.     *val = def_val;
  72. }
  73.  
  74. void get_string(res, val, def_val)
  75. char *res;
  76. char **val;
  77. char *def_val;
  78. {
  79.   char *string;
  80.  
  81.   string = XGetDefault(display, PRG_NAME, res);
  82.   if(string) {
  83.     *val = string;
  84.   } else {
  85.     *val = def_val;
  86.   }
  87. }
  88.  
  89. int get_color(res, val, def_val)
  90. char *res;
  91. XColor *val;
  92. char *def_val;
  93. {
  94.   char *string;
  95.   int found = False;
  96.  
  97.   string = XGetDefault(display, PRG_NAME, res);
  98.   if(string)
  99.     if(XParseColor(display, cmap, string, val))
  100.         found = True;
  101.   if(!found)
  102.     if(XParseColor(display, cmap, def_val, val))
  103.         found = True;
  104.   if(!found)
  105.     return 0;
  106.   if(!XAllocColor(display, cmap, val))
  107.     return 0;
  108.   return 1;
  109. }
  110.  
  111. int init_screen()
  112. {
  113.   int i;
  114.   char *win_name = "XSokoban";
  115.   char *icon_name = "XSokoban";
  116.   XSizeHints size_hints;
  117.   XWMHints wm_hints;
  118.   XSetWindowAttributes win_attr;
  119.   XClassHint classhint;
  120.   XGCValues revvals, values;
  121.   XTextProperty Win_Name, Icon_Name;
  122.   char *font_name;
  123.   char *string;
  124.   int temp, tempwalls = 1;
  125.  
  126.   if((display = XOpenDisplay(NULL)) == NULL) {
  127.     return E_NODISPLAY;
  128.   }
  129.   display_alloc = 1;
  130.  
  131.   get_string("fontname", &font_name, FONT);
  132.   if((font_info = XLoadQueryFont(display, font_name)) == NULL) {
  133.     return E_NOFONT;
  134.   }
  135.   font_alloc = 1;
  136.  
  137.   screen = DefaultScreen(display);
  138.   cmap = DefaultColormap(display, screen);
  139.   depth = DefaultDepth(display, screen);
  140.  
  141.   if(!get_color("foreground", &foreg, "white"))
  142.     return E_NOCOLOR;
  143.   if(!get_color("background", &backg, "black"))
  144.     return E_NOCOLOR;
  145.   if(!get_color("border", &bordr, "white"))
  146.     return E_NOCOLOR;
  147.   if(!get_color("cursor", &curs, "white"))
  148.     return E_NOCOLOR;
  149.   if(!optbitmap) {
  150.     get_string("bitmaps", &string, NULL);
  151.     if(string) {
  152.       strcpy(bitfilepath, string);
  153.       optbitmap = 1;
  154.       tempwalls = 0;
  155.     }
  156.   }
  157.  
  158.   if(!optwalls || !tempwalls) {
  159.     get_int("fancyWalls", &optwalls, tempwalls);
  160.   }
  161.  
  162.   width = MAXCOL * BIT_W;
  163.   height = MAXROW * BIT_H + 50;
  164.  
  165.   size_hints.min_width = size_hints.width = size_hints.max_width = width;
  166.   size_hints.min_height = size_hints.height = size_hints.max_height = height;
  167.   size_hints.x = size_hints.y = 0;
  168.  
  169.   size_hints.flags = (PSize | PPosition | PMinSize | PMaxSize);
  170.  
  171.   wm_hints.initial_state = NormalState;
  172.   wm_hints.input = True;
  173.  
  174.   wm_hints.flags = (StateHint | InputHint);
  175.  
  176.   classhint.res_class = classhint.res_name = PRG_NAME;
  177.  
  178.   this_curs = XCreateFontCursor(display, DEF_CURSOR);
  179.   XRecolorCursor(display, this_curs, &curs, &backg);
  180.  
  181.   win_attr.background_pixel = backg.pixel;
  182.   win_attr.border_pixel = bordr.pixel;
  183.   win_attr.backing_store = Always;
  184.   win_attr.event_mask = (KeyPressMask | ExposureMask);
  185.   win_attr.cursor = this_curs;
  186.  
  187.   if(XStringListToTextProperty(&win_name, 1, &Win_Name) == NULL) {
  188.     return E_NOMEM;
  189.   }
  190.  
  191.   if(XStringListToTextProperty(&icon_name, 1, &Icon_Name) == NULL) {
  192.     return E_NOMEM;
  193.   }
  194.  
  195.   win = XCreateWindow(display, RootWindow(display, screen), 0, 0, width,
  196.               height, 4, CopyFromParent, InputOutput, CopyFromParent,
  197.               (CWBackPixel | CWBorderPixel | CWBackingStore |
  198.                CWEventMask | CWCursor), &win_attr);
  199.  
  200.   XSetWMNormalHints(display, win, &size_hints);
  201.   XSetWMHints(display, win, &wm_hints);
  202.   XSetClassHint(display, win, &classhint);
  203.   XSetWMName(display, win, &Win_Name);
  204.   XSetWMIconName(display, win, &Icon_Name);
  205.  
  206.   for(i = 0; i < 2; i++) {
  207.     help[i] = XCreatePixmap(display, win, HELP_W, HELP_H, depth);
  208.   }
  209.   blank = XCreatePixmap(display, win, BIT_W, BIT_H, 1);
  210.   work = XCreatePixmap(display, win, width, height, depth);
  211.  
  212.   values.foreground = foreg.pixel;
  213.   revvals.foreground = backg.pixel;
  214.   values.background = backg.pixel;
  215.   revvals.background = foreg.pixel;
  216.   values.function  = revvals.function = GXcopy;
  217.   values.font = revvals.font = font_info->fid;
  218.  
  219.   gc = XCreateGC(display, win, (GCFunction | GCBackground | GCForeground |
  220.                 GCFont), &values);
  221.   rev = XCreateGC(display, blank, (GCFunction | GCBackground | GCForeground |
  222.                    GCFont), &revvals);
  223.   depth_rev = XCreateGC(display, win, (GCFunction | GCBackground |
  224.                        GCForeground | GCFont), &revvals);
  225.  
  226.   gc_alloc = 1;
  227.  
  228.   if(load_bitmaps() == E_NOBITMAP) return E_NOBITMAP;
  229.   make_help_windows();
  230.   pix_alloc = 1;
  231.  
  232.   XFillRectangle(display, blank, rev, 0, 0, BIT_W, BIT_H);
  233.  
  234.   clearscreen();
  235.  
  236.   XMapWindow(display, win);
  237.  
  238.   redisp_screen();
  239.  
  240.   return 0;
  241. }
  242.  
  243. load_one_bitmap(fname, altname, this_pix)
  244. char *fname;
  245. char *altname;
  246. Pixmap *this_pix;
  247. {
  248.   unsigned int dummy1, dummy2;
  249.   int dummy3, dummy4;
  250.   int load_fail;
  251.   if(optbitmap) {
  252.     chdir(bitfilepath);
  253.     if(XReadBitmapFile(display, win, fname, &dummy1, &dummy2, this_pix,
  254.                &dummy3, &dummy4) != BitmapSuccess) {
  255.       if(altname && *altname) {
  256.     printf("Unable to load %s/%s, trying alternate %s/%s\n",
  257.            bitfilepath, fname, bitfilepath, altname);
  258.     if(XReadBitmapFile(display, win, altname, &dummy1, &dummy2, this_pix,
  259.                &dummy3, &dummy4) != BitmapSuccess) {
  260.       load_fail = 1;
  261.       printf("Unable to load alternate %s/%s, trying defaults\n",
  262.          bitfilepath, altname);
  263.         } else {
  264.       return 0;
  265.     }
  266.       } else {
  267.     printf("Unable to load %s/%s, trying defaults.\n", bitfilepath, fname);
  268.       }
  269.     } else
  270.       return 0;
  271.   }
  272.   chdir(BITPATH);
  273.   if(!optbitmap || load_fail) {
  274.     if(XReadBitmapFile(display, win, fname, &dummy1, &dummy2, this_pix,
  275.                &dummy3, &dummy4) != BitmapSuccess) {
  276.       if(altname && *altname) {
  277.     printf("Unable to load default %s, trying alternate %s\n",
  278.            fname, altname);
  279.         if(XReadBitmapFile(display, win, altname, &dummy1, &dummy2, this_pix,
  280.                &dummy3, &dummy4) != BitmapSuccess) {
  281.       printf("Unable to load alternate %s!\n", altname);
  282.       return 1;
  283.         } else
  284.       return 0;
  285.       } else {
  286.     printf("Unable to load default %s!\n", fname);
  287.     return 1;
  288.       }
  289.     } else
  290.       return 0;
  291.   }
  292. }
  293.  
  294. int load_bitmaps()
  295. {
  296.   register int i;
  297.   int ret = 0;
  298.  
  299.   if(load_one_bitmap("man.xbm", NULL, &man)) ret = E_NOBITMAP;
  300.   if(load_one_bitmap("saveman.xbm", "man.xbm", &saveman)) ret = E_NOBITMAP;
  301.   if(load_one_bitmap("object.xbm", NULL, &object)) ret = E_NOBITMAP;
  302.   if(load_one_bitmap("treasure.xbm", NULL, &treasure)) ret = E_NOBITMAP;
  303.   if(load_one_bitmap("goal.xbm", NULL, &goal)) ret = E_NOBITMAP;
  304.   if(load_one_bitmap("floor.xbm", NULL, &floor)) ret = E_NOBITMAP;
  305.  
  306.   if(optwalls) {
  307.     for(i = 0; i < 16; i++) {
  308.       if(load_one_bitmap(wallname[i], "wall.xbm", &swalls[i])) ret = E_NOBITMAP;
  309.     }
  310.   } else {
  311.     if(load_one_bitmap("wall.xbm", NULL, &swalls[0])) ret = E_NOBITMAP;
  312.   }
  313.   return ret;
  314. }
  315.  
  316. make_help_windows()
  317. {
  318.   int i;
  319.   char *title =
  320.      "    Sokoban  --  X version by Joseph L. Traub  --  Help page %d";
  321.   char *next =
  322.      "     Press Enter to exit  --   Any other key for next page.";
  323.  
  324.   for (i = 0; i < 2; i++) {
  325.     XFillRectangle(display, help[i], depth_rev, 0, 0, HELP_W, HELP_H);
  326.     sprintf(buf, title, (i+1));
  327.     XDrawImageString(display, help[i], gc, 0, 11, buf, strlen(buf));
  328.     XDrawLine(display, help[i], gc, 0, 17, HELP_W, 17);
  329.     XDrawLine(display, help[i], gc, 0, HELP_H-20, HELP_W, HELP_H-20);
  330.     XDrawImageString(display, help[i], gc, 2, HELP_H-7, next, strlen(next));
  331.   }
  332.   for(i = 0; help_pages[i].textline != NULL; i++) {
  333.     XDrawImageString(display,help[help_pages[i].page], gc,
  334.              help_pages[i].xpos * (font_info->max_bounds.width), 
  335.              help_pages[i].ypos, help_pages[i].textline,
  336.              strlen(help_pages[i].textline));
  337.   }
  338.   XCopyPlane(display, man, help[0], gc, 0, 0, BIT_W, BIT_H, 180, 360, 1);
  339.   XCopyPlane(display, goal, help[0], gc, 0, 0, BIT_W, BIT_H, 270, 360, 1);
  340.   XCopyPlane(display, swalls[0], help[0], gc, 0, 0, BIT_W, BIT_H, 369, 360, 1);
  341.   XCopyPlane(display, object, help[0], gc, 0, 0, BIT_W, BIT_H, 477, 360, 1);
  342.   XCopyPlane(display, treasure, help[0], gc, 0, 0, BIT_W, BIT_H, 270, 400, 1);
  343.   XCopyPlane(display, saveman, help[0], gc, 0, 0, BIT_W, BIT_H, 477, 400, 1);
  344. }
  345.  
  346. shutdown_screen() {
  347.   int i;
  348.  
  349.   if(font_alloc) {
  350.     XFreeFont(display, font_info);
  351.   }
  352.   if(gc_alloc) {
  353.     XFreeGC(display, gc);
  354.     XFreeGC(display, rev);
  355.     XFreeGC(display, depth_rev);
  356.   }
  357.   if(pix_alloc) {
  358.     XFreePixmap(display, work);
  359.     XFreePixmap(display, man);
  360.     XFreePixmap(display, saveman);
  361.     XFreePixmap(display, goal);
  362.     XFreePixmap(display, treasure);
  363.     XFreePixmap(display, object);
  364.     XFreePixmap(display, floor);
  365.     for(i = 0; i < 16; i++) {
  366.       if(i < 2)
  367.         XFreePixmap(display, help[i]);
  368.       if(i == 0 || optwalls)
  369.         XFreePixmap(display, swalls[i]);
  370.     }
  371.     XFreePixmap(display, blank);
  372.   }
  373.   if(display_alloc)
  374.     XCloseDisplay(display);
  375. }
  376.  
  377. clearscreen() {
  378.   int i,j;
  379.  
  380.   XFillRectangle(display, work, depth_rev, 0, 0, width, height);
  381.   for(i = 0; i < MAXROW; i++)
  382.     for(j = 0; j < MAXCOL; j++)
  383.       XCopyPlane(display, floor, work, gc, 0, 0, BIT_W, BIT_H, j*BIT_W,
  384.             i*BIT_H, 1);
  385.   XDrawLine(display, work, gc, 0, BIT_H*MAXROW, BIT_W*MAXCOL, BIT_H*MAXROW);
  386. }
  387.  
  388. char event_loop()
  389. {
  390.   XEvent report;
  391.   char buf[1];
  392.   int bufsiz = 1;
  393.   KeySym keysym;
  394.   XComposeStatus compose;
  395.   int cntrl, shiftd;
  396.  
  397.   while(1) {
  398.     XNextEvent(display, &report);
  399.     switch (report.type) {
  400.       case Expose:
  401.     redisp_screen();
  402.     break;
  403.       case KeyPress:
  404.     buf[0] = NULL;
  405.     (void) XLookupString(&report.xkey, buf, bufsiz, &keysym, &compose);
  406.     cntrl = report.xkey.state & ControlMask;
  407.     shiftd = report.xkey.state & ShiftMask;
  408.     if(keysym == XK_Left) {
  409.       if (cntrl)
  410.         buf[0] = '\010';
  411.       else if (shiftd)
  412.         buf[0] = 'H';
  413.           else
  414.         buf[0] = 'h';
  415.     }
  416.     if(keysym == XK_Right) {
  417.       if (cntrl)
  418.         buf[0] = '\014';
  419.       else if (shiftd)
  420.         buf[0] = 'L';
  421.           else
  422.         buf[0] = 'l';
  423.     }
  424.     if(keysym == XK_Up) {
  425.       if (cntrl)
  426.         buf[0] = '\013';
  427.       else if (shiftd)
  428.         buf[0] = 'K';
  429.           else
  430.         buf[0] = 'k';
  431.     }
  432.     if(keysym == XK_Down) {
  433.       if (cntrl)
  434.         buf[0] = '\012';
  435.       else if (shiftd)
  436.         buf[0] = 'J';
  437.           else
  438.         buf[0] = 'j';
  439.     }
  440.     if(*buf)
  441.       return buf[0];
  442.     break;
  443.       default:
  444.     break;
  445.     }
  446.   }
  447. }
  448.  
  449. int redisp_screen() {
  450.   if(hlpscrn == -1)
  451.     XCopyArea(display, work, win, gc, 0, 0, width, height, 0, 0);
  452.   else {
  453.     XCopyArea(display, help[hlpscrn], win, gc, 0, 0, HELP_W, HELP_H, 0, 0);
  454.   }
  455.   XFlush(display);
  456. }
  457.  
  458. int showscreen() {
  459.   int mapchar(); 
  460.   register short i, j;
  461.  
  462.   for(i = 0; i < rows; i++)
  463.     for(j = 0; j < cols && map[i][j] != '\0'; j++)
  464.       mapchar(map[i][j], i, j);
  465.  
  466.   displevel();
  467.   disppackets();
  468.   dispsave();
  469.   dispmoves();
  470.   disppushes();
  471.   disphelp();
  472.   redisp_screen();
  473. }
  474.  
  475. int mapchar(c, i, j)
  476. char c;
  477. register short i, j;
  478. {
  479.   Pixmap this, get_obj_adr();
  480.   register short offset_row, offset_col;
  481.  
  482.   offset_col = BIT_W * (((MAXCOL - cols) / 2) + j);
  483.   offset_row = BIT_H * (((MAXROW - rows) / 2) + i);
  484.  
  485.   this = get_obj_adr(i, j, c);
  486.  
  487.  
  488.   XCopyPlane(display, this, work, gc, 0, 0, BIT_W, BIT_H, offset_col,
  489.         offset_row, 1);
  490. }
  491.  
  492. Pixmap get_obj_adr(i, j, c)
  493. register short i, j;
  494. char c;
  495. {
  496.   switch (c) {
  497.     case player:
  498.       return man;
  499.     case playerstore:
  500.       return saveman;
  501.     case store:
  502.       return goal;
  503.     case save:
  504.       return treasure;
  505.     case packet:
  506.       return object;
  507.     case wall:
  508.       if(optwalls)
  509.     return swalls[pickwall(i,j)];
  510.       else
  511.     return swalls[0];
  512.     case ground:
  513.       return floor;
  514.     default:
  515.       return blank;
  516.   }
  517. }
  518.  
  519. pickwall(i, j)
  520. int i, j;
  521. {
  522.    int ret = 0;
  523.  
  524.    if(i > 0 && map[i-1][j] == wall)
  525.      ret += 1;
  526.    if(i < rows && map[i+1][j] == wall)
  527.      ret += 4;
  528.    if(j < cols && map[i][j+1] == wall)
  529.      ret += 2;
  530.    if (j > 0 && map[i][j-1] == wall)
  531.      ret += 8;
  532.    return ret;
  533. }
  534.  
  535. draw_string(x, y, text)
  536. int x, y;
  537. char *text;
  538. {
  539.   int x_offset, y_offset;
  540.  
  541.   x_offset = x * font_info->max_bounds.width;
  542.   y_offset = y + font_info->ascent;
  543.  
  544.   XDrawImageString(display, work, gc, x_offset, y_offset, text, strlen(text));
  545. }
  546.  
  547. clear_string(x, y, len)
  548. int x, y, len;
  549. {
  550.   int i;
  551.  
  552.   for(i = 0; i < len; i++)
  553.     buf[i] = ' ';
  554.  
  555.   buf[len] = '\0';
  556.   draw_string(x, y, buf);
  557. }
  558.  
  559. displevel()
  560. {
  561.    sprintf(buf, "Level: %3d", level);
  562.    draw_string(0, STATUSLINE, buf);
  563. }
  564.  
  565. disppackets()
  566. {
  567.    sprintf(buf, "Packets: %3d", packets);
  568.    draw_string(12, STATUSLINE, buf);
  569. }
  570.  
  571. dispsave()
  572. {
  573.   sprintf(buf, "Saved: %3d", savepack);
  574.   draw_string(26, STATUSLINE, buf);
  575. }
  576.  
  577. dispmoves()
  578. {
  579.   sprintf(buf, "Moves: %5d", moves);
  580.   draw_string(38, STATUSLINE, buf);
  581. }
  582.  
  583. disppushes()
  584. {
  585.   sprintf(buf, "Pushes: %3d", pushes);
  586.   draw_string(52, STATUSLINE, buf);
  587. }
  588.  
  589. disphelp()
  590. {
  591.   draw_string(0, HELPLINE, "Press ? for help.");
  592. }
  593.  
  594. showhelp()
  595. {
  596.   int i = 0;
  597.   char c;
  598.   
  599.   hlpscrn = 0;
  600.   XCopyArea(display, help[i], win, gc, 0, 0, HELP_W, HELP_H, 0, 0);
  601.   XFlush(display);
  602.   while(c = event_loop()) {
  603.     switch(c) {
  604.       case '\015':
  605.     hlpscrn = -1;
  606.     return;
  607.       default:
  608.     i = (i+1)%2;
  609.     hlpscrn = i;
  610.     XCopyArea(display, help[i], win, gc, 0, 0, HELP_W, HELP_H, 0, 0);
  611.     XFlush(display);
  612.     }
  613.   }
  614. }
  615.  
  616. helpmessage()
  617. {
  618.   XBell(display,0);
  619.   redisp_screen();
  620. }
  621.